/*
 * AacHelper.cpp
 *
 *  Created on: 2015年12月7日
 *      Author: terry
 */

#include "AacHelper.h"
#include "TStringUtil.h"


namespace av
{

static const int s_freqTable[16] =
{
	96000, 88200, 64000, 48000,
	44100, 32000, 24000, 22050,
	16000, 12000, 11025, 8000,
	7350, 0, 0, 0
};


AacHelper::AacHelper()
{
}

AacHelper::~AacHelper()
{
}

int AacHelper::getFreqIndex(int freq)
{
	int idx = 8;
	size_t count = sizeof(s_freqTable)/sizeof(s_freqTable[0]);
	for (size_t i = 0; i < count; ++ i)
	{
		if (freq == s_freqTable[i])
		{
			idx = i;
			break;
		}
	}
	return idx;
}

std::string AacHelper::makeConfig(int profile, int freq, int channels)
{
	int idx = getFreqIndex(freq);
	uint8_t audioSpecificConfig[2];
	uint8_t audioObjectType = profile + 1;
	audioSpecificConfig[0] = (audioObjectType<<3) | (idx>>1);
	audioSpecificConfig[1] = (idx<<7) | (channels<<3);

	return comn::StringUtil::format("%02X%02x",
			audioSpecificConfig[0], audioSpecificConfig[1]);
}

bool AacHelper::makeAdtsHeader(int profile, int freq, int channels, int packetLen, uint8_t* buf, size_t size)
{
	if (size < ADTS_HEADER_SIZE)
	{
		return false;
	}

	int freqIdx = getFreqIndex(freq);

    // fill in ADTS data
    buf[0] = (uint8_t)0xFF;
    buf[1] = (uint8_t)0xF1;
    buf[2] = (uint8_t)(((profile)<<6) + (freqIdx<<2) +(channels>>2));
    buf[3] = (uint8_t)(((channels&3)<<6) + (packetLen>>11));
    buf[4] = (uint8_t)((packetLen&0x7FF) >> 3);
    buf[5] = (uint8_t)(((packetLen&7)<<5) + 0x1F);
    buf[6] = (uint8_t)0xFC;

	return true;
}

bool AacHelper::isAdts(uint8_t* buf, size_t size)
{
	if (size < ADTS_HEADER_SIZE)
	{
		return false;
	}

    return (buf[0] == 0xff) && ((buf[1] & 0xf0) == 0xf0);
}

bool AacHelper::parse(const uint8_t* buf, size_t size, int& profile, int& channels, int& samplerate)
{
	if (size < ADTS_HEADER_SIZE)
	{
		return false;
	}

	profile = buf[2] >> 6;
	int freqIdx = (buf[2] & 0x3C) >> 2;
	if (freqIdx < sizeof(s_freqTable) / sizeof(s_freqTable[0]))
	{
		samplerate = s_freqTable[freqIdx];
	}

	channels = ((buf[2] & 0x01) << 2) + (buf[3] >> 6);
	return true;
}


} /* namespace av */
